home *** CD-ROM | disk | FTP | other *** search
/ Over 1,000 Windows 95 Programs / Over 1000 Windows 95 Programs (Microforum) (Disc 2).iso / 1133 / neural.c < prev    next >
C/C++ Source or Header  |  1997-04-16  |  13KB  |  526 lines

  1. /*
  2. **
  3. **  File:           NEURAL.C
  4. **  Description:    Executes a back propagation neural network
  5. **  Platform:       Windows
  6. **
  7. **
  8. */
  9.  
  10. #include <math.h>
  11. #include <windows.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <malloc.h>
  15. #include "nndefs.h"
  16. #include "datamat.h"
  17. #include "params.h"
  18. #include "neural.h"
  19.  
  20. #define CIRCULAR
  21.  
  22.     float Random(float randz);
  23.     void Logit(const char* fmt, ...);
  24.     static char FMT_E[] = "%e ";
  25.  
  26.     int fgetstr (FILE *fd, LPSTR str);
  27.     int fgetint(FILE *fd);
  28.     long fgetlong(FILE *fd);
  29.     float fgetfloat(FILE *fd);
  30.  
  31. /*
  32. ** NCreateNeural
  33. **
  34. ** This function is called to create a neural network. Only the shell of the network
  35. ** is created. To complete the creation of the network the import network function
  36. ** will create the other members.
  37. ** 
  38. **
  39. ** Arguments:
  40. **
  41. **      None
  42. **
  43. ** Returns:
  44. **
  45. **      NEURAL        A pointer to the created neural network or a NULL if not created
  46. */
  47.  
  48. NEURAL *NCreateNeural(  )
  49. {   
  50.     NEURAL *pN;
  51.     pN = (NEURAL*) malloc (sizeof(NEURAL));
  52.     
  53.     pN->m_version = REVLEVEL;
  54.     pN->m_istate = pN->m_ninputs = pN->m_noutputs = pN->m_nhidden = 0;
  55.     pN->m_params = NULL;
  56.     pN->m_sumerr2 = 0.f;
  57.     pN->m_cnt = 0;
  58.     pN->m_itmax = 2;
  59.     pN->m_dm=NULL;
  60.  
  61.     pN->m_ni    = NULL;
  62.     pN->m_nout    = NULL;
  63.     pN->m_hinputw    = NULL;
  64.     pN->m_houtputv    = NULL;
  65.     pN->m_htheta    = NULL;
  66.     pN->m_oinputw    = NULL;
  67.     pN->m_otheta    = NULL;
  68.  
  69. #ifdef CIRCULAR
  70.     pN->m_hcircw    = NULL;
  71.     pN->m_ocircw    = NULL;
  72. #endif
  73. #ifdef VERBOSE
  74.     Logit ("CNeural null constructor\n");
  75. #endif
  76.     return pN;
  77.  
  78. }
  79.  
  80. /*
  81. ** NDeleteNeural
  82. **
  83. ** This function is called to delete a neural network. All memory used by the network
  84. ** is freed. 
  85. ** 
  86. **
  87. ** Arguments:
  88. **
  89. **      Neural *pN        A pointer to the neural network to be deleted
  90. **
  91. ** Returns:
  92. **
  93. **      Nothing
  94. */
  95.  
  96. void NDeleteNeural(NEURAL *pN )
  97. {
  98. #ifdef VERBOSE
  99.     Logit ("CNeural destructor\n");
  100. #endif  
  101.  
  102.     if (pN->m_istate&NN_PARAMSLOADED) free (pN->m_params);
  103.  
  104.     if (pN->m_noutputs) {
  105. #ifdef VERBOSE
  106.         Logit ("   Destroying in=%d hid=%d out=%d\n",pN->m_ninputs,pN->m_nhidden,pN->m_noutputs);
  107. #endif
  108.         free_2d_floats (pN->m_hinputw, pN->m_nhidden);
  109.         free_2d_floats (pN->m_oinputw, pN->m_noutputs);
  110.  
  111.         free_2d_floats (pN->m_iinputw, pN->m_noutputs);
  112.         free (pN->m_ni);
  113.         free (pN->m_houtputv);
  114.         free (pN->m_htheta);
  115.         free (pN->m_otheta);
  116.         free (pN->m_nout);
  117. #ifdef CIRCULAR
  118.         free (pN->m_ocircw);
  119.         free (pN->m_hcircw);
  120. #endif
  121.     }
  122.     if (pN->m_istate&NN_DYNAMIC) {
  123.         if(pN->m_noutputs) {
  124. #ifdef VERBOSE
  125.             Logit ("   Destroy dynamic\n");
  126. #endif
  127.             free_2d_floats (pN->m_hlastdelta, pN->m_nhidden);
  128.             free_2d_floats (pN->m_olastdelta,pN->m_noutputs);
  129.             free_2d_floats (pN->m_ilastdelta,pN->m_noutputs);
  130.             free (pN->m_hlastvar);
  131.             free (pN->m_hlearn);
  132.             free (pN->m_htlearn);
  133.             free (pN->m_olastvar);
  134.             free (pN->m_otraining);
  135.             free (pN->m_olearn);
  136.             free (pN->m_otlearn);
  137.         }
  138.     }
  139.     if (pN->m_istate&NN_DATAMAT) {
  140. #ifdef VERBOSE
  141.         Logit ("   Destroy DM\n");
  142. #endif
  143.         DDeleteDataMat(pN->m_dm);
  144.     }
  145.     free (pN);
  146. #ifdef VERBOSE
  147.     Logit("Done deleting CNeural\n");
  148. #endif
  149. }
  150.  
  151.  
  152. /*
  153. ** NGetROutput
  154. **
  155. ** This function is called to get the re-scaled value of the neural network's output.
  156. ** The re-scaled value is the number as the user presented to the network. The network
  157. ** scales all numbers to a range of 0.2 to 0.8, where as the inputs and outputs to the
  158. ** neural network can be of any range.
  159. ** 
  160. **
  161. ** Arguments:
  162. **
  163. **      NEURAL *pN          A pointer to the neural network structure
  164. **      const int neuron    The index to the desired output
  165. **
  166. ** Returns:
  167. **
  168. **      float        The value of the selected neural network's output
  169. */
  170.  
  171. float NGetROutput(NEURAL *pN, const int neuron)
  172. {
  173.     return (DRescale(pN->m_dm, pN->m_nout[neuron],'O',neuron));
  174. }
  175.  
  176. /*
  177. ** NGetRInput
  178. **
  179. ** This function is called to get the re-scaled value of the neural network's input.
  180. ** The re-scaled value is the number as the user presented to the network. The network
  181. ** scales all numbers to a range of 0.2 to 0.8, where as the inputs and outputs to the
  182. ** neural network can be of any range.
  183. ** 
  184. **
  185. ** Arguments:
  186. **
  187. **      NEURAL *pN          A pointer to the neural network structure
  188. **      const int neuron    The index to the desired input
  189. **
  190. ** Returns:
  191. **
  192. **      float        The value of the selected neural network's input
  193. */
  194.  
  195. float NGetRInput(NEURAL *pN, const int neuron)
  196. {
  197.     return (DRescale(pN->m_dm, pN->m_ni[neuron],'I',neuron));
  198. }
  199.                                                  
  200. /*
  201. ** NSetRInput
  202. **
  203. ** This function is called to set the value of the neural network's input.
  204. ** The value is scaled to the range that is optimal for this network.
  205. ** 
  206. **
  207. ** Arguments:
  208. **
  209. **      NEURAL *pN          A pointer to the neural network structure
  210. **      const int neuron    The index to the desired input
  211. **
  212. ** Returns:
  213. **
  214. **      Nothing
  215. */
  216.  
  217. void NSetRInput(NEURAL *pN, const int neuron, float f)
  218. {
  219.     pN->m_ni[neuron] = DScale(pN->m_dm, f,'I',neuron);
  220. }
  221.  
  222. /*
  223. ** NFeedForward
  224. **
  225. ** This function is called to evaluate the selected neural network. The network inputs
  226. ** must of been already loaded. After calling this function the network's outputs can
  227. ** be retrived.
  228. ** 
  229. **
  230. ** Arguments:
  231. **
  232. **      NEURAL *pN          A pointer to the neural network structure
  233. **
  234. ** Returns:
  235. **
  236. **      Nothing
  237. */
  238.  
  239. void NFeedForward(NEURAL *pN)
  240. {
  241.     int i,j;
  242.     float sum1;
  243. #ifdef CIRCULAR
  244.     float csum;
  245. #endif
  246.  
  247. // calculate the outputs of the hidden layer 
  248.                            
  249.     for (i=0; i < pN->m_nhidden; i++) {
  250.         for (sum1=0.f,j=0; j < pN->m_ninputs; j++)
  251.             sum1 += (pN->m_ni[j] * pN->m_hinputw[i][j] );
  252.         sum1 += pN->m_htheta[i];
  253. #ifdef CIRCULAR
  254.         if (pN->m_params->m_TrainFlags&TF_CBPHIDDEN) { 
  255.             for (csum=0.f,j=0; j < pN->m_ninputs; j++) {
  256.                 csum += (pN->m_ni[j] * pN->m_ni[j] );
  257.             }
  258.             sum1 += (csum * pN->m_hcircw[i]);
  259.         }
  260. #endif
  261.         pN->m_houtputv[i] = afunc (sum1);
  262.     }
  263.  
  264. // connect hidden layer 1 to output neurons 
  265.  
  266.     for (j=0; j < pN->m_noutputs; j++) {
  267.         for (sum1=0.f,i=0; i < pN->m_nhidden; i++)
  268.             sum1 += (pN->m_houtputv[i] * pN->m_oinputw[j][i]);
  269.         if (pN->m_params->m_TrainFlags & TF_NOINTOOUT) {
  270.             for (i=0; i < pN->m_ninputs; i++)
  271.                 sum1 += (pN->m_ni[i] * pN->m_iinputw[j][i]);
  272.         }
  273.         sum1 += pN->m_otheta[j];
  274. #ifdef CIRCULAR
  275.         if (pN->m_params->m_TrainFlags&TF_CBPOUTPUT) { 
  276.             for (csum=0.f,i=0; i < pN->m_ninputs; i++) {
  277.                 csum += (pN->m_ni[i] * pN->m_ni[i] );
  278. //                TRACE ("hi=%e csum=%e ocircw=%e\n",m_houtputv[i],csum,m_ocircw[j]);    
  279.             }
  280.             sum1 += (csum * pN->m_ocircw[j]);
  281.         }
  282. #endif
  283.         pN->m_nout[j] = afunc (sum1);
  284.     }
  285. }
  286.  
  287. /*
  288. ** ntransl
  289. **
  290. ** This function is used internally by the import neural network function.
  291. ** 
  292. **
  293. ** Arguments:
  294. **
  295. **      char *cdummy          A pointer to a character string
  296. **
  297. ** Returns:
  298. **
  299. **      int        returns the tranlated string or a -1 if the string doesn't start with 'N'
  300. */
  301.  
  302. int ntransl(char *cdummy)
  303. {
  304.     int val=0;
  305.  
  306.     if (cdummy[0] != 'N') return -1;
  307.     val = atoi(&cdummy[1]);
  308.     return val;
  309. }
  310.  
  311. /*
  312. ** NImportNetwork
  313. **
  314. ** This function is called to import a neural network from an ENN file. This file is
  315. ** an ASCII exported file from NNMODEL.
  316. ** 
  317. **
  318. ** Arguments:
  319. **
  320. **      NEURAL *pN          A pointer to the already created network
  321. **      FILE *fd            A pointer to a opened ENN file
  322. **
  323. ** Returns:
  324. **
  325. **      int        returns a zero if the network was imported without error. A -1 is return on error.
  326. */
  327.  
  328. int NImportNetwork (NEURAL *pN, FILE *fd)
  329. {
  330.     int i,j,sel,stat,h,o;
  331.     static char cdummy[80];
  332.  
  333.     stat=ImportParams(fd,pN->m_params);
  334.     if (stat) return stat;
  335.     pN->m_sumerr2 = 0.f;
  336. #ifdef VERBOSE
  337.     Logit("Loading neural\n");
  338. #endif
  339.  
  340. top:
  341.     stat = fgetstr(fd,cdummy);
  342.     if (stat==EOF) goto errorexit;
  343.     
  344.  
  345.     sel = ntransl(cdummy);
  346.     switch (sel) {
  347.     case 99:
  348.         pN->m_dm = DCreateDataMat();
  349.         stat=DImportDataMat(pN->m_dm,fd);
  350. #ifdef VERBOSE
  351.         Logit("Finished import NN\n");
  352. #endif
  353.         return stat;
  354.  
  355.         break;
  356.     default:
  357.         goto errorexit;
  358.         break;
  359.     case 1:
  360.         pN->m_istate = fgetint(fd);
  361.         pN->m_ninputs = fgetint(fd);
  362.         pN->m_nhidden = fgetint(fd);
  363.         pN->m_noutputs = fgetint(fd);
  364.         pN->m_cnt = fgetlong(fd);
  365.         pN->m_istate |= NN_PARAMSLOADED;
  366.         pN->m_ni = (float*) malloc (sizeof(float)*pN->m_ninputs);
  367.         pN->m_houtputv = (float*) malloc (sizeof(float)*pN->m_nhidden);
  368.         pN->m_htheta = (float*) malloc (sizeof(float)*pN->m_nhidden);
  369.         pN->m_otheta = (float*) malloc (sizeof(float)*pN->m_noutputs);
  370.         pN->m_nout = (float*) malloc (sizeof(float)*pN->m_noutputs);
  371.         pN->m_hinputw = alloc_2d_floats (pN->m_nhidden,pN->m_ninputs);
  372.         pN->m_oinputw = alloc_2d_floats (pN->m_noutputs,pN->m_nhidden);
  373.         pN->m_iinputw = alloc_2d_floats (pN->m_noutputs,pN->m_ninputs);
  374.  
  375.         if (pN->m_istate&NN_DYNAMIC) {
  376.             pN->m_hlastvar      = (float*) malloc (sizeof(float)*pN->m_nhidden);
  377.             pN->m_hlearn        = (float*) malloc (sizeof(float)*pN->m_nhidden);
  378.             pN->m_htlearn       = (float*) malloc (sizeof(float)*pN->m_nhidden);
  379.             pN->m_olastvar      = (float*) malloc (sizeof(float)*pN->m_noutputs);
  380.             pN->m_otraining     = (float*) malloc (sizeof(float)*pN->m_noutputs);
  381.             pN->m_olearn        = (float*) malloc (sizeof(float)*pN->m_noutputs);
  382.             pN->m_otlearn       = (float*) malloc (sizeof(float)*pN->m_noutputs);
  383.             pN->m_hlastdelta    = alloc_2d_floats (pN->m_nhidden,pN->m_ninputs);
  384.             pN->m_olastdelta    = alloc_2d_floats (pN->m_noutputs,pN->m_nhidden);
  385.             pN->m_ilastdelta    = alloc_2d_floats (pN->m_noutputs,pN->m_ninputs);
  386.  
  387.         }
  388.  
  389.         for (i=0;i<pN->m_ninputs;i++) pN->m_ni[i] = 0.f;
  390.         for (h=0;h<pN->m_nhidden;h++) {
  391.             for (i=0;i<pN->m_ninputs;i++) pN->m_hinputw[h][i] = 0.f;
  392.             pN->m_houtputv[h] = pN->m_htheta[h] = 0.f;
  393.         }
  394.         for (o=0;o<pN->m_noutputs;o++) {
  395.             for (h=0;h<pN->m_nhidden;h++) pN->m_oinputw[o][h] = 0.f;
  396.             for (i=0;i<pN->m_ninputs;i++) pN->m_iinputw[o][i] = 0.f;
  397.             pN->m_otheta[o] = pN->m_nout[o] = 0.f;
  398.         }
  399.         break;
  400.     case 2:
  401.         for (i=0;i<pN->m_ninputs;i++)
  402.             for (j=0;j<pN->m_nhidden;j++) pN->m_hinputw[j][i]=fgetfloat(fd);
  403.         break;
  404.     case 3:
  405.         for (i=0;i<pN->m_nhidden;i++) pN->m_htheta[i]=fgetfloat(fd);
  406.         break;
  407.     case 4:
  408.         for (i=0;i<pN->m_noutputs;i++)
  409.         for (j=0;j<pN->m_nhidden;j++) pN->m_oinputw[i][j]=fgetfloat(fd);
  410.         break;
  411.     case 5:
  412.         for (i=0;i<pN->m_noutputs;i++) pN->m_otheta[i]=fgetfloat(fd);
  413.         break;
  414.     // Now load data for the dynamic part of CNeural class
  415.     case 6:
  416.         for (i=0;i<pN->m_nhidden;i++) pN->m_hlastvar[i]=fgetfloat(fd);
  417.         break;
  418.     case 7:
  419.         for (i=0;i<pN->m_nhidden;i++) pN->m_hlearn[i]=fgetfloat(fd);
  420.         break;
  421.     case 8:
  422.         for (i=0;i<pN->m_nhidden;i++) pN->m_htlearn[i]=fgetfloat(fd);
  423.         break;
  424.     case 9:
  425.         for (i=0;i<pN->m_noutputs;i++) pN->m_olastvar[i]=fgetfloat(fd);
  426.         break;
  427.     case 10:
  428.         for (i=0;i<pN->m_noutputs;i++) pN->m_olearn[i]=fgetfloat(fd);
  429.         break;
  430.     case 11:
  431.         for (i=0;i<pN->m_noutputs;i++) pN->m_otlearn[i]=fgetfloat(fd);
  432.         break;
  433.     case 12:
  434.         for (i=0;i<pN->m_noutputs;i++)
  435.             for (j=0;j<pN->m_ninputs;j++) pN->m_iinputw[i][j]=fgetfloat(fd);
  436.         break;
  437. #ifdef CIRCULAR
  438.     case 13:
  439.         pN->m_hcircw = (float*) malloc (sizeof(float)*pN->m_nhidden);
  440.         pN->m_ocircw = (float*) malloc (sizeof(float)*pN->m_noutputs);
  441.         for (i=0;i<pN->m_nhidden;i++) pN->m_hcircw[i] = fgetfloat(fd);
  442.         for (i=0;i<pN->m_noutputs;i++) pN->m_ocircw[i] = fgetfloat(fd);
  443.         break;
  444. #endif
  445.     }
  446.     goto top;
  447.  
  448. errorexit:          
  449.     return -1;
  450. }
  451.  
  452. /*
  453. ** LoadNetwork
  454. **
  455. ** This function is called to create and import a neural network from an ENN file. 
  456. ** This file is an ASCII exported file from NNMODEL.
  457. ** 
  458. **
  459. ** Arguments:
  460. **
  461. **      char *filename         A pointer to a characer string containing the file name
  462. **
  463. ** Returns:
  464. **
  465. **      NEURAL        returns a pointer to the imported network or a NULL if tere was an error
  466. */
  467.  
  468. NEURAL *LoadNetwork (char *filename) {
  469.     FILE *fd;
  470.     int stat;
  471.     PARAMS *tparams;
  472.     NEURAL *tneural;
  473.  
  474.     fd = fopen(filename,"r");
  475.     if (fd == NULL) {
  476.         Logit("File not found %s\n",filename);
  477.         return NULL;
  478.     }
  479.  
  480.     tparams = (PARAMS*) malloc (sizeof(PARAMS));
  481.     tneural = (NEURAL*) malloc (sizeof(NEURAL));
  482.     tneural->m_params = tparams;
  483.     tneural->m_istate |= NN_PARAMSLOADED;
  484.  
  485.     stat = NImportNetwork(tneural,fd);
  486.     fclose(fd);
  487.  
  488.  
  489.     if (stat) {
  490.         NDeleteNeural (tneural);
  491. #ifdef VERBOSE
  492.         Logit ("Error importing network\n");
  493. #endif
  494.         return NULL;
  495.     }
  496.     return tneural;
  497. }
  498.  
  499. /*
  500. ** NInterrogate
  501. **
  502. ** This function is called to load a neural network's inputs, evaluate the network
  503. ** and then retrieves the network's outputs
  504. ** 
  505. **
  506. ** Arguments:
  507. **
  508. **      NEURAL *pN          A pointer to the already created network
  509. **      float *Ivec            A pointer to an array of input values
  510. **      float *Ovec            A pointer to an array of output values
  511. **
  512. ** Returns:
  513. **
  514. **      Nothing
  515. */
  516.  
  517. void NInterrogate(NEURAL *pN,float *Ivec,float *Ovec)
  518. {
  519.     int i;
  520.  
  521.     for (i=0; i < pN->m_ninputs; i++) pN->m_ni[i] = DScale(pN->m_dm,Ivec[i],'I',i);
  522.     NFeedForward(pN);
  523.     for (i=0; i < pN->m_noutputs; i++) Ovec[i] = DRescale(pN->m_dm,pN->m_nout[i],'O',i);
  524. }
  525.  
  526.